
package com.cainli.task;

import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

import android.content.Context;
import android.content.res.Resources;

import com.cainli.swingworker.ScheduleLinkedBlockingQueue;
import com.cainli.swingworker.SchedulingRule;
import com.cainli.swingworker.ThreadPoolExecutor;
import com.cainli.swingworker.WorkerUtilities;

public abstract class Task<ReturnResult, InterParam> extends AbstractTask<ReturnResult, InterParam> implements SchedulingRule{

    private BlockingScope blockScope;
    private Object sources;
    private String group;
    
    // task service
    private static TaskService taskService;
    
    private static TaskMonitor taskMonitor;
    
    public Task(Context context, Resources resources) {
        super(context, resources);
    }

    /**
     * 构造函数
     * 
     * @param context 上下文
     */
    public Task(Context context) {
        this(context, BlockingScope.NONE, null);
    }
    
    public Task(Context context,BlockingScope blockScope,Object sources)
    {
        super(context);
        this.blockScope = blockScope;
        this.sources = sources;
    }
    
    /**
     * 构造函数
     * @param context 上下文
     * @param blockScope 阻止类型
     * @param sources 源头（View）
     * @param titleRes 标题资源ID
     * @param descriptionRes 描述资源ID
     */
    public Task(Context context,BlockingScope blockScope,Object sources,int descriptionRes)
    {
        super(context);
        setDescription(context.getResources().getString(descriptionRes));
        this.blockScope = blockScope;
        this.sources = sources;
    }
    
    /**
     * 构造函数
     * @param context 上下文
     * @param blockScope 阻止类型
     * @param sources 源头（View）
     * @param titleRes 标题资源ID
     * @param descriptionRes 描述资源ID
     */
    public Task(Context context,BlockingScope blockScope,Object sources,int titleRes,int descriptionRes)
    {
        super(context);
        setTitle(context.getResources().getString(titleRes));
        setDescription(context.getResources().getString(descriptionRes));
        this.blockScope = blockScope;
        this.sources = sources;
    }
    
    /**
     * 获取分组
     * @return 分组
     */
    public String getGroup() {
        return group;
    }

    /**
     * 设置分组，同一分组的任务同时只能执行一个
     * @param group 分组
     */
    public void setGroup(String group) {
        this.group = group;
    }
    
    @Override
    public void execute() {
        // 如果取消了,则不执行
        if (!isCancelled()) {
            if (getInputBlocker() == null) {
                setInputBlocker(createInputBlocker());
            }
            getService().execute(this);
        }
    }
    
    public void execute(long delay) {
        if (delay <= 0) {
            execute();
        } else {
            WorkerUtilities.invokeInLooper(new Runnable() {

                @Override
                public void run() {
                    execute();
                }
            }, delay);
        }
    }

    @Override
    public boolean isConflicting(SchedulingRule rule) {
        if(rule instanceof Task<?, ?>)
        {
            // 双方分组都不为空,并且双方都未取消
            if(group != null
                    && ((Task)rule).group != null
                    && !isCancelled()
                    && !((Task)rule).isCancelled())
            {
                return group == ((Task)rule).group;
            }
        }
        return false;
    }
    
    public synchronized static TaskService getService()
    {
        if(taskService == null)
        {
            ScheduleLinkedBlockingQueue<Runnable> queue = new ScheduleLinkedBlockingQueue<Runnable>();
            ThreadFactory threadFactory = 
                new ThreadFactory() {
                    final ThreadFactory defaultFactory = 
                        Executors.defaultThreadFactory();
                    public Thread newThread(final Runnable r) {
                        Thread thread = 
                            defaultFactory.newThread(r);
                        thread.setName("Task-" 
                            + thread.getName());
                        thread.setDaemon(true);
                        return thread;
                    }
                };

            ThreadPoolExecutor executorService = new ThreadPoolExecutor(5,
                    128, 1L, TimeUnit.SECONDS,
                    queue, threadFactory);
            
            queue.setExecutor((ThreadPoolExecutor) executorService);
            taskService = new TaskService("default",executorService);
            taskMonitor = new TaskMonitor(taskService);
        }
        return taskService;
    }
    
    /**
     * 获取TaskMonitor
     * @return 获取TaskMonitor，可以添加监听器来
     */
    public synchronized static TaskMonitor getTaskMonitor()
    {
        if(taskService == null)
        {
            getService();
        }
        return taskMonitor;
    }

    private InputBlocker createInputBlocker() {
        // TODO 还没实现
        return null;
    }
}
